package basetype

import (
	"github.com/pkg/errors"
	"strings"
	"unicode/utf8"
	"unsafe"
)

/**
golang 中一般情况下字符串直接用+ 、strings.Builder、strings.Join三种拼接效率都较高
	+ 连接适用于短小的、常量字符串（明确的，非变量），因为编译器会给我们优化。
	Join是比较统一的拼接，不太灵活
	fmt和buffer基本上不推荐
	builder从性能和灵活性上，都是上佳的选择。

*/

//增加一个参数cap，让使用者告诉我们需要的容量大小
func StringBuilder(p []string, cap int) string {

	var b strings.Builder
	l := len(p)
	b.Grow(cap)
	for i := 0; i < l; i++ {
		b.WriteString(p[i])
	}
	return b.String()
}

/*
  @param  s  字符串
  @param  startIndex  起始下标(inclue)
  @param  endIndex  结束下标(uninclue)
  @return  string
*/
func Substring(s string, startIndex int, endIndex int) string {

	s0 := []rune(s)
	sLen := len(s0)

	if startIndex > endIndex {
		panic(errors.New("startIndex  large than endIndex"))
	}

	if startIndex < 0 || startIndex >= sLen {
		panic(errors.New("startIndex error"))
	}

	if endIndex < 0 || endIndex >= sLen {
		panic(errors.New("startIndex error"))
	}

	return string(s0[startIndex:endIndex])

}

func SubStrDecodeRuneInString(s string, length int) string {
	var size, n int
	for i := 0; i < length && n < len(s); i++ {
		_, size = utf8.DecodeRuneInString(s[n:])
		n += size
	}

	return s[:n]
}

func SubStrRange(s string, length int) string {
	// range 是按字符迭代的，并非字节
	var n, i int
	for i = range s {
		if n == length {
			break
		}

		n++
	}

	return s[:i]
}

/*
  @param  s  字符串
  @param  index  下标
  @return  rune
*/
func RuneAt(s string, index int) rune {
	return []rune(s)[index]
}

func str2bytes(s string) []byte {
	x := (*[2]uintptr)(unsafe.Pointer(&s))
	h := [3]uintptr{x[0], x[1], x[1]}
	return *(*[]byte)(unsafe.Pointer(&h))
}

func bytes2str(b []byte) string {
	return *(*string)(unsafe.Pointer(&b))
}
